package com.suredy.security.service;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Restrictions;
import org.springframework.stereotype.Service;

import com.suredy.core.service.BaseSrvWithEntity;
import com.suredy.security.entity.PermissionEntity;
import com.suredy.security.entity.UnitEntity;
import com.suredy.security.entity.User2RoleEntity;
import com.suredy.security.entity.UserEntity;
import com.suredy.security.model.User;

@Service("UserSrv")
public class UserSrv extends BaseSrvWithEntity<UserEntity> {

	@Override
	public DetachedCriteria getDc(UserEntity t) {
		DetachedCriteria dc = super.getDc(t);

		if (t == null) {
			return dc;
		}

		if (!StringUtils.isBlank(t.getId())) {
			dc.add(Restrictions.eqOrIsNull("id", t.getId()));
		}
		if (!StringUtils.isBlank(t.getUniqueCode())) {
			dc.add(Restrictions.eq("uniqueCode", t.getUniqueCode()));
		}
		if (!StringUtils.isBlank(t.getPassword())) {
			dc.add(Restrictions.eq("password", t.getPassword()));
		}

		if (t.getAvailable() != null) {
			dc.add(Restrictions.eq("available", t.getAvailable()));
		}
		if (t.getUnit() != null) {
			dc.add(Restrictions.eq("unit", t.getUnit()));
		}
		return dc;
	}

	public User getById(String userId) {
		if (StringUtils.isBlank(userId)) {
			return null;
		}
		UserEntity po = this.get(userId);
		return po.toVO();
	}

	public List<User> getAll() {
		UserEntity search = new UserEntity();
		search.setAvailable(1);
		LinkedHashMap<String, Boolean> order = new LinkedHashMap<String, Boolean>();
		order.put("unit", false);
		List<UserEntity> pos = this.readByEntity(search, order);
		List<User> ret = new ArrayList<User>();
		for (UserEntity po : pos) {
			ret.add(po.toVO());
		}
		return ret;
	}

	public Long Count(String deptId) {

		String ql = "";
		UnitEntity unit = null;
		Object ret = null;
		if (StringUtils.isBlank(deptId)) {
			ql = "SELECT COUNT(*) FROM UserEntity T WHERE available=1";
			ret = this.readSingleByQL(ql);
		} else {
			unit = new UnitEntity();
			unit.setId(deptId);
			ql = "SELECT COUNT(*) FROM UserEntity T WHERE available=1 and unit=?";
			ret = this.readSingleByQL(ql, unit);
		}

		return (Long) ret;
	}

	public List<User> getAll(Integer page, Integer size) {
		UserEntity search = new UserEntity();
		search.setAvailable(1);
		LinkedHashMap<String, Boolean> order = new LinkedHashMap<String, Boolean>();
		order.put("sort", false);
		List<UserEntity> pos = this.readByEntity(search, page, size, order);
		List<User> ret = new ArrayList<User>();
		for (UserEntity po : pos) {
			ret.add(po.toVO());
		}
		return ret;
	}

	public User getUser(String uniqueCode, String password) {
		if (StringUtils.isBlank(uniqueCode)) {
			return null;
		}
		UserEntity search = new UserEntity();
		search.setUniqueCode(uniqueCode);
		search.setPassword(password);

		UserEntity po = this.readSingleByEntity(search);
		if (po == null) {
			return null;
		}
		return po.toVO();
	}

	public User getUser(String uniqueCode) {
		if (StringUtils.isBlank(uniqueCode)) {
			return null;
		}
		UserEntity search = new UserEntity();
		search.setUniqueCode(uniqueCode);
		UserEntity po = this.readSingleByEntity(search);
		if (po == null) {
			return null;
		}
		return po.toVO();
	}

	public int countUsers(String unitId) {
		String sql = "SELECT COUNT(ID_E_YH) FROM T_E_YH WHERE ID_E_ZZDY=?";
		BigInteger result = (BigInteger) super.readSingleBySQL(sql, unitId);
		int ret = result.intValue();
		return ret;
	}

	public List<String> getRoles(String userId) {
		String sql = "SELECT ID, ROLEID, USERID FROM T_SECURITY_USER2ROLE WHERE USERID=?";
		List<User2RoleEntity> result = super.readBySQL(sql, User2RoleEntity.class, userId);
		List<String> ret = new ArrayList<String>();
		for (User2RoleEntity m : result) {
			ret.add(m.getRole().getId());
		}
		return ret;
	}

	public List<String> getPermissions(String userCode) {
		List<String> permissions = new ArrayList<String>();
		permissions.addAll(getRolePermissions(userCode));
		permissions.addAll(getUserPermissions(userCode));
		return permissions;
	}

	public List<String> getRolePermissions(String userCode) {
		final String sql = "SELECT p.ID, p.ACTION, p.RESOURCEID " + "FROM T_E_YH u LEFT JOIN T_SECURITY_USER2ROLE ur ON (u.ID_E_YH=ur.USERID) " + "LEFT JOIN T_E_QZ r ON (ur.ROLEID=r.ID_E_QZ) " + "JOIN T_SECURITY_ROLE2PERMISSION rp ON (r.ID_E_QZ=rp.ROLEID) " + "JOIN T_SECURITY_PERMISSION p ON (rp.PERMISSIONID=p.ID) " + "WHERE u.WYMC=?";
		List<PermissionEntity> result = super.readBySQL(sql, PermissionEntity.class, userCode);
		List<String> ret = new ArrayList<String>();
		for (PermissionEntity p : result) {
			ret.add(p.getResource().getUri());
		}
		return ret;
	}

	public List<String> getUserPermissions(String userCode) {
		final String sql = "SELECT p.ID, p.ACTION, p.RESOURCEID  " + "FROM T_E_YH u LEFT JOIN T_SECURITY_USER2PERMISSION up ON (u.ID_E_YH=up.USERID) " + "JOIN T_SECURITY_PERMISSION p ON (up.PERMISSIONID=p.ID) " + "WHERE u.WYMC=?";
		List<PermissionEntity> result = super.readBySQL(sql, PermissionEntity.class, userCode);
		List<String> ret = new ArrayList<String>();
		for (PermissionEntity p : result) {
			ret.add(p.getResource().getUri());
		}
		return ret;
	}

	public int updateUserPswd(String id, String oldPswd, String newPswd) {
		String ql = "UPDATE UserEntity SET password = ? where id = ? and password = ?";

		int count = this.updateByQL(ql, newPswd, id, oldPswd);

		return count;
	}

	public List<User> getByDeptCode(Integer page, Integer size, String deptId) {
		UserEntity search = new UserEntity();
		search.setAvailable(1);
		if (!StringUtils.isBlank(deptId)) {
			UnitEntity unit = new UnitEntity();
			unit.setId(deptId);
			search.setUnit(unit);
		}
		LinkedHashMap<String, Boolean> order = new LinkedHashMap<String, Boolean>();
		order.put("sort", false);
		List<UserEntity> pos = this.readByEntity(search, page, size, order);
		List<User> ret = new ArrayList<User>();
		for (UserEntity po : pos) {
			ret.add(po.toVO());
		}
		return ret;
	}

}
